package com.flyco.modules.stm.controller;

import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.flyco.common.constant.StockConstant;
import com.flyco.modules.pms.entity.PmsProduct;
import com.flyco.modules.pms.service.IPmsProductService;
import com.flyco.modules.stm.entity.*;
import com.flyco.modules.stm.model.StmMoveItemModel;
import com.flyco.modules.stm.service.*;
import com.flyco.modules.stm.vo.StmStockVO;
import org.apache.shiro.SecurityUtils;
import com.flyco.poi.excel.ExcelImportUtil;
import com.flyco.poi.excel.def.NormalExcelConstants;
import com.flyco.poi.excel.entity.ExportParams;
import com.flyco.poi.excel.entity.ImportParams;
import com.flyco.poi.excel.view.EntityExcelView;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.common.api.vo.Result;
import com.flyco.common.system.query.QueryGenerator;
import com.flyco.common.util.oConvertUtils;
import com.flyco.modules.stm.vo.StmMovePage;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.flyco.common.aspect.annotation.AutoLog;

/**
 * @Description: 门店移库单表
 * @Author: flyco
 * @Date: 2021-01-15
 * @Version: V1.0
 */
@Api(tags = "门店移库单表")
@RestController
@RequestMapping("/f/stm/stmMove")
@Slf4j
public class StmMoveController {
    @Autowired
    private IStmMoveService stmMoveService;
    @Autowired
    private IStmMoveItemService stmMoveItemService;
    @Autowired
    private IPmsProductService pmsProductService;
    @Autowired
    private IStmStoreInfoService stmStoreInfoService;
    @Autowired
    private IStmSalesService stmSalesService;
    @Autowired
    private IStmStockService stmStockService;

    /**
     * 分页列表查询
     *
     * @param stmMove
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "门店移库单表-分页列表查询")
    @ApiOperation(value = "门店移库单表-分页列表查询", notes = "门店移库单表-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(StmMove stmMove,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<StmMove> queryWrapper = QueryGenerator.initQueryWrapper(stmMove, req.getParameterMap());
        Page<StmMove> page = new Page<StmMove>(pageNo, pageSize);
        IPage<StmMove> pageList = stmMoveService.page(page, queryWrapper);
        if (pageList.getTotal() > 0) {
            List<StmSales> salesList = stmSalesService.list();
            Map<Long, String> salesMap = salesList.stream().collect(Collectors.toMap(StmSales::getId, StmSales::getName, (key1, key2) -> key2));
            List<StmStoreInfo> storeInfos = stmStoreInfoService.list();
            Map<Long, String> storeInfoMaps = storeInfos.stream().collect(Collectors.toMap(StmStoreInfo::getStoreId, StmStoreInfo::getName, (key1, key2) -> key2));
            pageList.getRecords().forEach(move -> {
                if (oConvertUtils.isNotEmpty(move.getStoreId())) {
                    if (storeInfoMaps.containsKey(move.getStoreId())) {
                        move.setStoreId_dictText(storeInfoMaps.get(move.getStoreId()));
                    } else {
                        if (Objects.equals(0L , move.getStoreId() )) {
                            move.setStoreId_dictText("线上商城");
                        }
                    }
                }
                if (oConvertUtils.isNotEmpty(move.getConfirmSalesId())) {
                    if (salesMap.containsKey(move.getConfirmSalesId())) {
                        move.setConfirmSalesId_dictText(salesMap.get(move.getConfirmSalesId()));
                    }
                }
                if (oConvertUtils.isNotEmpty(move.getCreateSalesId())) {
                    if (salesMap.containsKey(move.getCreateSalesId())) {
                        move.setCreateSalesId_dictText(salesMap.get(move.getCreateSalesId()));
                    }
                }
            });
        }
        return Result.ok(pageList);
    }

    /**
     * 添加
     *
     * @param stmMovePage
     * @return
     */
    @AutoLog(value = "门店移库单表-添加")
    @ApiOperation(value = "门店移库单表-添加", notes = "门店移库单表-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody StmMovePage stmMovePage) {
        StmMove stmMove = new StmMove();
        BeanUtils.copyProperties(stmMovePage, stmMove);
		stmMove.setStatus(0);
        stmMoveService.save(stmMove);
        return Result.ok("添加成功！");
    }

    /**
     * 编辑
     *
     * @param stmMovePage
     * @return
     */
    @AutoLog(value = "门店移库单表-编辑")
    @ApiOperation(value = "门店移库单表-", notes = "门店移库单表-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody StmMovePage stmMovePage) {
        StmMove stmMove = new StmMove();
        BeanUtils.copyProperties(stmMovePage, stmMove);
        stmMoveService.updateById(stmMove);
        return Result.ok("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "门店移库单表-通过id删除")
    @ApiOperation(value = "门店移库单表-通过id删除", notes = "门店移库单表-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) Long id) {
        stmMoveService.delMain(id);
        return Result.ok("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "门店移库单表-批量删除")
    @ApiOperation(value = "门店移库单表-批量删除", notes = "门店移库单表-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.stmMoveService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "门店移库单表-通过id查询")
    @ApiOperation(value = "门店移库单表-通过id查询", notes = "门店移库单表-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) Long id) {
        StmMove stmMove = stmMoveService.getById(id);
        return Result.ok(stmMove);
    }




    /**
     * 移动
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "门店移库单-移动")
    @PostMapping(value = "/move")
    public Result<?> move(@RequestBody String[] ids) {
        LambdaQueryWrapper<StmMove> query = new LambdaQueryWrapper<>();
        query.in(StmMove::getId,ids);
        List<StmMove> moves = stmMoveService.list(query);

        LambdaQueryWrapper<StmMoveItem> itemQuery = new LambdaQueryWrapper<>();
        itemQuery.in(StmMoveItem::getMoveId,ids);
        List<StmMoveItem> moveItems = stmMoveItemService.list(itemQuery);
        Map<Long, List<StmMoveItem>> itemMap = moveItems.stream().collect(Collectors.groupingBy(e -> e.getMoveId()));

        moves.forEach(move -> {
            if(Arrays.asList(3).contains(move.getStatus())){
                if (itemMap.containsKey(move.getId())) {
                    List<StmMoveItem> items = itemMap.get(move.getId());
                    List<StmStockVO> outStockVOList = new ArrayList<>();
                    List<StmStockVO> inStockVOList = new ArrayList<>();
                    items.forEach(item->{
                        StmStockVO vo = BeanUtils.instantiateClass(StmStockVO.class);
                        vo.setProductId(item.getProductId());
                        vo.setProductSn(item.getProductSn());
                        vo.setStockType(item.getFromStockType());
                        vo.setProductQty(item.getProductQty());
                        outStockVOList.add(vo);
                        StmStockVO voIn = BeanUtils.instantiateClass(StmStockVO.class);
                        BeanUtils.copyProperties(vo, voIn);
                        voIn.setStockType(item.getToStockType());
                        inStockVOList.add(voIn);
                    });
                    String changeReason = "库移出库";
                    stmStockService.stockInOut(outStockVOList, move.getStoreId(), StockConstant.STOCK_OUT, StockConstant.STOCK_OUT_TYPE_MOVE, StockConstant.RECEIPT_TYPE_MOVE, move.getId().toString(), changeReason );
                    changeReason = "库移入库";
                    stmStockService.stockInOut(inStockVOList, move.getStoreId(), StockConstant.STOCK_IN, StockConstant.STOCK_IN_TYPE_MOVE, StockConstant.RECEIPT_TYPE_MOVE, move.getId().toString(), changeReason );
                    StmMove updateMove = new StmMove();
                    updateMove.setStatus(5);
                    updateMove.setId(move.getId());
                    stmMoveService.updateById(updateMove);
                }
            }
        });
        return Result.ok("移库成功！");
    }



    //===========================以下是子表信息操作相关API====================================

    /**
     * 通过主表id查询门店移库单明细表
     *
     * @param stmMoveItem
     * @return
     */
    @AutoLog(value = "门店移库单明细表-通过主表id查询")
    @ApiOperation(value = "门店移库单明细表-通过主表id查询", notes = "门店移库单明细表-通过主表id查询")
    @GetMapping(value = "/listStmMoveItemByMainId")
    public Result<?> listStmMoveItemByMainId(StmMoveItem stmMoveItem,
                                             @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                             @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                             HttpServletRequest req) {
        if (stmMoveItem.getMoveId() != null) {
            QueryWrapper<StmMoveItem> queryWrapper = QueryGenerator.initQueryWrapper(stmMoveItem, req.getParameterMap());
            Page<StmMoveItem> page = new Page<StmMoveItem>(pageNo, pageSize);
            IPage<StmMoveItem> pageList = stmMoveItemService.page(page, queryWrapper);
            return Result.ok(pageList);
        } else {
            return Result.error("请选择一条记录");
        }
    }

    /**
     * 添加门店移库单明细表
     *
     * @param stmMoveItemModel
     * @return
     */
    @AutoLog(value = "门店移库单明细表-添加")
    @ApiOperation(value = "门店移库单明细表-添加", notes = "门店移库单明细表-添加")
    @PostMapping(value = "/addStmMoveItem")
    public Result<?> addStmMoveItem(@RequestBody StmMoveItemModel stmMoveItemModel) {
        if (oConvertUtils.isEmpty(stmMoveItemModel) || oConvertUtils.isEmpty(stmMoveItemModel.getMoveId()) || oConvertUtils.isEmpty(stmMoveItemModel.getDetailList())) {
            return Result.error("数据为空！");
        }
        StmMove stmMove = stmMoveService.getById(stmMoveItemModel.getMoveId());
        if (oConvertUtils.isEmpty(stmMove)) {
            return Result.error("移库单主表记录为空，请检查后重试！");
        }
        if (stmMove.getStatus() > 0) {
            return Result.error("该调拨单不是初始状态，不可再增加商品！");
        }
        List<String> productSns = stmMoveItemModel.getDetailList().stream().map(StmMoveItem::getProductSn).collect(Collectors.toList());
        long count = productSns.stream().distinct().count();
        if (count < productSns.size()) {
            return Result.error("新添加的记录中存在重复数据，请重核对后重试！");
        }
        LambdaQueryWrapper<PmsProduct> query = new LambdaQueryWrapper<>();
        query.in(PmsProduct::getProductSn, productSns);
        List<PmsProduct> products = pmsProductService.list(query);
        Map<String, Long> productMaps = products.stream().collect(Collectors.toMap(PmsProduct::getProductSn, PmsProduct::getId, (key1, key2) -> key2));
        List<StmMoveItem> stmMoveItemList = stmMoveItemService.selectByMainId(stmMoveItemModel.getMoveId());
        if (oConvertUtils.isNotEmpty(stmMoveItemList) && stmMoveItemList.size() > 0) {
            List<Long> productIds = products.stream().map(PmsProduct::getId).collect(Collectors.toList());
            List<Long> dbItemProductIds = stmMoveItemList.stream().map(StmMoveItem::getProductId).collect(Collectors.toList());
            List<Long> mixes = productIds.stream().filter(r -> dbItemProductIds.contains(r)).collect(Collectors.toList());
            if (oConvertUtils.isNotEmpty(mixes) && mixes.size() > 0) {
                return Result.error("新添加的记录已存在，请重核对后重试！");
            }
        }
		stmMoveItemModel.getDetailList().forEach(r -> {
            r.setMoveId(stmMoveItemModel.getMoveId());
            r.setProductId(productMaps.get(r.getProductSn()));
        });
		stmMoveItemService.saveBatch(stmMoveItemModel.getDetailList());
        return Result.ok("添加门店移库单明细成功！");
    }


    /**
     * 编辑门店移库单明细表
     *
     * @param stmMoveItem
     * @return
     */
    @AutoLog(value = "门店移库单明细表-编辑")
    @ApiOperation(value = "门店移库单明细表-编辑", notes = "门店移库单明细表-编辑")
    @PutMapping("/editStmMoveItem")
    public Result<?> editStmMoveItem(@RequestBody StmMoveItem stmMoveItem) {
        StmMove stmMove = stmMoveService.getById(stmMoveItem.getMoveId());
        if (oConvertUtils.isEmpty(stmMove)) {
            return Result.error("移库单主表记录为空，请检查后重试！");
        }
        if (stmMove.getStatus() > 0) {
            return Result.error("该调拨单不是初始状态，不可修改商品！");
        }
        stmMoveItemService.updateById(stmMoveItem);
        return Result.ok("编辑门店移库单明细表成功！");
    }

    /**
     * 通过id删除门店移库单明细表
     *
     * @param id
     * @return
     */
    @AutoLog(value = "门店移库单明细表-通过id删除")
    @ApiOperation(value = "门店移库单明细表-通过id删除", notes = "门店移库单明细表-通过id删除")
    @DeleteMapping(value = "/deleteStmMoveItem")
    public Result<?> deleteStmMoveItem(@RequestParam(name = "id", required = true) Long id) {
        StmMoveItem stmMoveItem = stmMoveItemService.getById(id);
        StmMove stmMove = stmMoveService.getById(stmMoveItem.getMoveId());
        if (oConvertUtils.isEmpty(stmMove)) {
            return Result.error("移库单主表记录为空，请检查后重试！");
        }
        if (stmMove.getStatus() > 0) {
            return Result.error("该调拨单不是初始状态，不可删除商品！");
        }
        stmMoveItemService.removeById(id);
        return Result.ok("删除门店移库单明细表成功！");
    }

    /**
     * 批量删除门店移库单明细表
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "门店移库单明细表-批量删除")
    @ApiOperation(value = "门店移库单明细表-批量删除", notes = "门店移库单明细表-批量删除")
    @DeleteMapping(value = "/deleteBatchStmMoveItem")
    public Result<?> deleteBatchStmMoveItem(@RequestParam(name = "ids", required = true) String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("参数不识别！");
        }
        this.stmMoveItemService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");

    }


    /**
     * 导出excel
     *
     * @param request
     * @param stmMove
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, StmMove stmMove) {
        // Step.1 组装查询条件
        QueryWrapper<StmMove> queryWrapper = QueryGenerator.initQueryWrapper(stmMove, request.getParameterMap());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<StmMovePage> pageList = new ArrayList<StmMovePage>();
        List<StmMove> stmMoveList = stmMoveService.list(queryWrapper);
        for (StmMove temp : stmMoveList) {
            StmMovePage vo = new StmMovePage();
            BeanUtils.copyProperties(temp, vo);
            List<StmMoveItem> stmMoveItemList = stmMoveItemService.selectByMainId(temp.getId());
            vo.setStmMoveItemList(stmMoveItemList);
            pageList.add(vo);
        }
        //Step.3 调用AutoPoi导出Excel
        ModelAndView mv = new ModelAndView(new EntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "门店移库单表");
        mv.addObject(NormalExcelConstants.CLASS, StmMovePage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("门店移库单表数据", "导出人:" + sysUser.getRealname(), "门店移库单表"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<StmMovePage> list = ExcelImportUtil.importExcel(file.getInputStream(), StmMovePage.class, params);
                for (StmMovePage page : list) {
                    StmMove po = new StmMove();
                    BeanUtils.copyProperties(page, po);
                    stmMoveService.saveMain(po, page.getStmMoveItemList());
                }
                return Result.ok("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.ok("文件导入失败！");
    }
}
